package com.zhongen.oa.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsHeaders;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsRequest;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsResponse;
import com.aliyun.dingtalkcontact_1_0.models.ListEmpLeaveRecordsResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiUserGetRequest;
import com.dingtalk.api.request.OapiV2DepartmentListsubRequest;
import com.dingtalk.api.request.OapiV2UserListRequest;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
import com.dingtalk.api.response.OapiV2UserListResponse;
import com.taobao.api.ApiException;
import com.zhongen.admin.api.dto.UserDTO;
import com.zhongen.admin.api.entity.SysDept;
import com.zhongen.admin.api.entity.SysPost;
import com.zhongen.admin.api.entity.SysUser;
import com.zhongen.admin.api.feign.RemoteDeptService;
import com.zhongen.admin.api.feign.RemotePostService;
import com.zhongen.admin.api.feign.RemoteUserService;
import com.zhongen.common.core.constant.SecurityConstants;
import com.zhongen.common.core.util.R;
import com.zhongen.dingtalk.GetDingDingLoginToken;
import com.zhongen.oa.service.DingTalkService;
import com.zhongen.oa.service.ProjectBasicInfoService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@AllArgsConstructor
public class DingTalkServiceImpl implements DingTalkService {

	private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");

	private final GetDingDingLoginToken getDingDingLoginToken;

	private final RemoteDeptService remoteDeptService;

	private final RemoteUserService remoteUserService;

	private final RemotePostService remotePostService;

	private final ProjectBasicInfoService projectBasicInfoService;

	/**
	 * 同步钉钉组织架构及人员数据
	 */
	@Override
	public void getDeptAndUserFromDingTalk() {
		// 获取access_token
		String accessToken = getDingDingLoginToken.getToken();
		// 初始化 deptId
		Long deptId = 1L;
		getResponseFromDingTalk(accessToken, deptId);

		// 获取当前日期和时间
		Date date = new Date();
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(calendar.DATE, -180);
		date = calendar.getTime();
		// 创建ISO 8601格式的日期时间字符串
		// 2023-12-31T00:00:00Z
		Instant timestamp = date.toInstant();

		List<SysUser> userList = resignationList(accessToken, timestamp.toString());
		if (ObjectUtils.isNotEmpty(userList)) {
			UserDTO userDTO = new UserDTO();
			userDTO.setResignationInfo(userList);
			remoteUserService.updateByUsernames(userDTO, SecurityConstants.FROM_IN);
		}
	}

	/**
	 * @param deptId 部门id
	 */

	private void getResponseFromDingTalk(String accessToken, Long deptId) {
		// 获取 并添加 添加 当前部门 下的人员数据 同时维系关系表

		// 人员数据入库
		getUsersInDept(accessToken, deptId);
		// 获取一个client
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
		OapiV2DepartmentListsubRequest request = new OapiV2DepartmentListsubRequest();
		request.setDeptId(deptId);
		request.setLanguage("zh_CN");
		// 获取到相应的response
		OapiV2DepartmentListsubResponse response = null;
		try {
			response = client.execute(request, accessToken);
		}
		catch (ApiException e) {
			throw new RuntimeException(e);
		}
		// 获取到response 中的 result 中的 deptbase 集合
		List<OapiV2DepartmentListsubResponse.DeptBaseResponse> deptBaseResponseList = response.getResult();
		// 对获取到的非空 钉钉中的 baseDepts 做处理获取
		if (!deptBaseResponseList.isEmpty()) {
			deptBaseResponseList.forEach(e -> {
				SysDept sysDept = new SysDept();
				sysDept.setDeptId(e.getDeptId());
				sysDept.setParentId(e.getParentId());
				sysDept.setName(e.getName());
				sysDept.setSortOrder(1);
				sysDept.setCreateBy("dingtalk");
				sysDept.setUpdateBy("dingtalk");
				boolean updateSuccess = remoteDeptService.innerUpdate(sysDept, SecurityConstants.FROM_IN);
				if (!updateSuccess) {
					remoteDeptService.save(sysDept, SecurityConstants.FROM_IN);
				}
				// 递归调用
				getResponseFromDingTalk(accessToken, e.getDeptId());
			});
		}

	}

	/**
	 * 获取当前层级下的各个部门的用户集合
	 */
	private void getUsersInDept(String accessToken, Long deptId) {
		List<SysPost> posts = new ArrayList<>();
		R<List<SysPost>> postResult = remotePostService.listPosts("Y");
		if (postResult.getData() != null) {
			posts.addAll(postResult.getData());
		}
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list");
		OapiV2UserListRequest req = new OapiV2UserListRequest();
		req.setDeptId(deptId);
		req.setCursor(0L);
		req.setSize(100L);
		OapiV2UserListResponse rsp = null;

		try {
			rsp = client.execute(req, accessToken);
			JSONArray jsonArray = JSONObject.parseObject(rsp.getBody()).getJSONObject("result").getJSONArray("list");
			jsonArray.forEach(e -> {
				JSONObject jsonObject = JSONObject.parseObject(e.toString());
				UserDTO sysUser = new UserDTO();

				// 查询用户详情（为获取入职时间）
				DingTalkClient client1 = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
				OapiUserGetRequest req1 = new OapiUserGetRequest();
				req1.setUserid(jsonObject.getString("userid"));
				req1.setHttpMethod("GET");
				OapiUserGetResponse rsp1 = null;
				try {
					rsp1 = client1.execute(req1, accessToken);
					JSONObject jsonDetails = JSONObject.parseObject(rsp1.getBody());
					if (ObjectUtils.isNotEmpty(jsonDetails.getString("hiredDate"))) {
						// 入职时间
						LocalDate entryDate = timestampToLocalDate(Long.parseLong(jsonDetails.getString("hiredDate")));
						sysUser.setEntryDate(entryDate);
					}
				}
				catch (ApiException ex) {
					throw new RuntimeException(ex);
				}

				sysUser.setDeptId(jsonObject.getJSONArray("dept_id_list").getLong(0));
				JSONArray deptIdList = jsonObject.getJSONArray("dept_id_list");
				if (!deptIdList.isEmpty()) {
					sysUser.setDeptIds(JSONObject.parseArray(deptIdList.toJSONString(), Long.class));
				}
				sysUser.setName(jsonObject.getString("name"));
				sysUser.setPhone(jsonObject.getString("mobile"));
				sysUser.setUsername(jsonObject.getString("mobile"));
				sysUser.setCreateBy("dingtalk");
				sysUser.setUpdateBy("dingtalk");
				ArrayList<Long> roles = new ArrayList<>();

				String title = jsonObject.getString("title");
				if (StrUtil.isNotEmpty(title) && !"null".equals(title)) {
					List<Long> list = posts.stream()
						.filter(post -> StrUtil.equals(post.getPostCode(), title))
						.map(SysPost::getPostId)
						.toList();
					if (list.isEmpty()) {
						SysPost post = new SysPost();
						post.setPostName(title);
						post.setPostCode(title);
						post.setCreateBy("dingtalk");
						post.setUpdateBy("dingtalk");
						post.setPostSort(1);
						if (remotePostService.savePost(post, "Y").getData()) {
							R<List<SysPost>> result = remotePostService.listPosts("Y");
							if (result.getData() != null) {
								posts.clear();
								posts.addAll(result.getData());
								list = posts.stream()
									.filter(item -> StrUtil.equals(item.getPostCode(), title))
									.map(SysPost::getPostId)
									.toList();
							}
						}
					}
					sysUser.setPost(list);
				}
				sysUser.setRole(roles);
				SysUser user = remoteUserService.innerQueryUserByCondition("phone", sysUser.getUsername(),
						SecurityConstants.FROM_IN);
				if (null == user) {
					sysUser.setNickname(jsonObject.getString("name"));
					roles.add(2L);
					sysUser.setPassword(jsonObject.getString("mobile"));
					remoteUserService.innerAddUser(sysUser, SecurityConstants.FROM_IN);
				}
				else {
					remoteUserService.innerUpdateUser(sysUser, SecurityConstants.FROM_IN);
				}
			});
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	private LocalDate timestampToLocalDate(long timestamp) {
		// 创建 Instant 对象并指定时区
		ZoneId zoneId = ZoneId.systemDefault();
		Instant instant = Instant.ofEpochMilli(timestamp);

		// 根据时区获取 LocalDateTime 对象
		LocalDateTime dateTime = LocalDateTime.ofInstant(instant, zoneId);

		// 提取年、月、日信息
		int year = dateTime.getYear();
		Month month = dateTime.getMonth();
		int dayOfMonth = dateTime.getDayOfMonth();

		// 构造 LocalDate 对象
		LocalDate localDate = LocalDate.of(year, month, dayOfMonth);
		return localDate;
	}

	// 离职列表
	@SneakyThrows
	private List<SysUser> resignationList(String accessToken, String timestamp) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		// 离职名单username - leaveTime
		List<SysUser> userList = new ArrayList<>();

		Config config = new Config();
		config.protocol = "https";
		config.regionId = "central";
		com.aliyun.dingtalkcontact_1_0.Client client = new com.aliyun.dingtalkcontact_1_0.Client(config);
		ListEmpLeaveRecordsHeaders listEmpLeaveRecordsHeaders = new ListEmpLeaveRecordsHeaders();
		listEmpLeaveRecordsHeaders.xAcsDingtalkAccessToken = accessToken;
		ListEmpLeaveRecordsRequest listEmpLeaveRecordsRequest = new ListEmpLeaveRecordsRequest().setStartTime(timestamp)
			// 如果该参数不传，开始时间距离当前时间不能超过365天。
			// 如果该参数传参，开始时间和结束时间跨度不能超过365天。
			// .setEndTime("2023-12-31T00:00:00Z")
			.setNextToken("0")
			.setMaxResults(10);
		try {
			ListEmpLeaveRecordsResponse listEmpLeaveRecordsResponse = client.listEmpLeaveRecordsWithOptions(
					listEmpLeaveRecordsRequest, listEmpLeaveRecordsHeaders, new RuntimeOptions());
			if (ObjectUtils.isNotEmpty(listEmpLeaveRecordsResponse.getBody())
					&& ObjectUtils.isNotEmpty(listEmpLeaveRecordsResponse.getBody().getRecords())) {
				List<ListEmpLeaveRecordsResponseBody.ListEmpLeaveRecordsResponseBodyRecords> records = listEmpLeaveRecordsResponse
					.getBody()
					.getRecords();
				for (ListEmpLeaveRecordsResponseBody.ListEmpLeaveRecordsResponseBodyRecords record : records) {
					SysUser sysUser = new SysUser();
					sysUser.setName(record.getName());
					sysUser.setPhone(record.getMobile());
					sysUser.setLeaveDate(LocalDate.parse(record.getLeaveTime().split("T")[0], formatter));
					userList.add(sysUser);
				}
			}
		}
		catch (TeaException err) {
			if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
				// err 中含有 code 和 message 属性，可帮助开发定位问题
			}
		}
		catch (Exception _err) {
			TeaException err = new TeaException(_err.getMessage(), _err);
			if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
				// err 中含有 code 和 message 属性，可帮助开发定位问题
			}
		}
		return userList;
	}

}
